package com.library.books.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.library.books.domain.*;
import com.library.books.domain.vo.*;
import com.library.books.domain.vo.borrow.BooksJoinBorrowRecord;
import com.library.books.domain.wsdata.BookOnLend;
import com.library.books.domain.wsdata.BookOnRenew;
import com.library.books.domain.wsdata.BookOnReturn;
import com.library.books.mapper.BooksBorrowMapper;
import com.library.books.service.*;
import com.library.common.constant.SysConfigConstants;
import com.library.common.enums.BooksBorrowStatus;
import com.library.common.enums.BooksCopyStatus;
import com.library.common.enums.BooksRuleRenew;
import com.library.common.enums.BorrowRecordType;
import com.library.common.gdxx.push.InternalPush;
import com.library.common.utils.DateUtils;
import com.library.common.utils.StringUtils;
import com.library.common.utils.spring.SpringUtils;
import com.library.common.wspoint.point.GlobalServerPoint;
import com.library.system.service.ISysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 借阅Service业务层处理
 *
 * @author hb
 * @date 2024-10-14
 */
@Slf4j
@Service
public class BooksBorrowServiceImpl extends ServiceImpl<BooksBorrowMapper, BooksBorrow> implements IBooksBorrowService
{

    @Resource
    private IBorrowRecordService borrowRecordService;

    @Resource
    private IBorrowFineRecordService borrowFineRecordService;

    @Resource
    private IBooksRuleService borrowRunService;

    @Resource
    private IBooksCopyService booksCopyService;

    @Resource
    private IStudentService studentService;

    @Resource
    private IBookShelfService shelfService;

    @Resource
    private GlobalServerPoint globalServerPoint;

    @Resource
    IGDXXPushService igdxxPushService;

    @Resource
    InternalPush internalPush;

    /**
     * 查询借阅列表
     *
     * @param booksBorrow 借阅
     * @return 借阅
     */
    @Override
    public List<BooksBorrow> selectBooksBorrowList(BooksBorrow booksBorrow) {
        return baseMapper.selectBooksBorrowList(booksBorrow);
    }

    /**
     * 借阅功能
     *
     * @param booksBorrowList 借阅集合
     * @return 借阅集合
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public boolean borrowingFunction(List<BooksJoinBorrowRecord> booksBorrowList) {
        // 当前借阅人
        List<Student> students = studentService.list(Wrappers.lambdaQuery(Student.class).in(Student::getStudentCardNumber, booksBorrowList.stream().map(BooksJoinBorrowRecord::getBorrowCard).distinct().collect(Collectors.toList())));
        if(students.size() == 0) {
            throw new RuntimeException("借阅人信息有误");
        }
        // 书架信息
        List<BookShelf> bookShelfs = shelfService.list(Wrappers.lambdaQuery(BookShelf.class).in(BookShelf::getBookShelfId, booksBorrowList.stream().map(BooksJoinBorrowRecord::getBookShelfId).distinct().collect(Collectors.toList())));

        booksBorrowList.forEach(item -> {
            /// 测试用的
//            item.setCreateTime(new Date(1725442470475L));
             item.setCreateTime(DateUtils.getNowDate());
            item.setBorrowShouldReturnTime(DateUtils.addDays(item.getCreateTime(),item.getBorrowDays()));
            // 学生信息
            Student student = students.stream().filter(s -> s.getStudentCardNumber().equals(item.getBorrowCard())).findFirst().orElse(null);
            if(student == null) {
                throw new RuntimeException("借阅书籍《"+ item.getBooksName() +"》时，未找到["+ item.getBorrowCard() +"]学生信息");
            }
            item.setStudentName(student.getStudentName());
            item.setStudentNumber(student.getStudentNumber());

            BookShelf bookShelf = bookShelfs.stream().filter(s -> s.getBookShelfId().equals(item.getBookShelfId())).findFirst().orElse(null);
            if(bookShelf != null) {
                item.setBookShelfId(bookShelf.getBookShelfId());
                item.setBookShelfName(bookShelf.getBookShelfName());
            }else {
                item.setBookShelfId(null);
                item.setBookShelfName(null);
            }

            // 根据书籍副本id获取借阅规则
            BooksJoinBooksCopyJoinBooksRule booksJoinBooksCopyJoinBooksRule = borrowRunService.selectBooksRuleInfoAndBooksInfoByBooksCopyId(item.getBooksCopyId());
            if (item.getBorrowDays() > booksJoinBooksCopyJoinBooksRule.getBooksRuleTerm()) {
                throw new RuntimeException("书籍：" + booksJoinBooksCopyJoinBooksRule.getBooksName() + "借阅天数不能超过" + booksJoinBooksCopyJoinBooksRule.getBooksRuleTerm() + "天");
            }
        });
        // 批量添加借阅信息（拿到借阅id）
        baseMapper.batchSaveBooksBorrows(booksBorrowList);

        // 修改书籍副本状态集合
        List<BooksCopy> booksCopyList = new ArrayList<>();
        // 借阅记录集合
        List<BorrowRecord> borrowRecordList = new ArrayList<>();

        booksBorrowList.forEach(item -> {
            BooksCopy booksCopy = new BooksCopy();
            booksCopy.setBooksCopyId(item.getBooksCopyId());
            booksCopy.setBooksCopyStatus(BooksCopyStatus.LEND.getCode());
            // 自助机的时候是没有用户存在的
            booksCopy.setCreateId(item.getCreateId());
            booksCopy.setCreateBy(item.getCreateBy());
            booksCopy.setUpdateId(item.getUpdateId());
            booksCopy.setUpdateBy(item.getUpdateBy());
            booksCopyList.add(booksCopy);

            BorrowRecord borrowRecord = new BorrowRecord();
            borrowRecord.setBorrowId(item.getBorrowId());
            borrowRecord.setBorrowCard(item.getBorrowCard());
            borrowRecord.setBorrowLendDays(item.getBorrowDays());
            borrowRecord.setBorrowLendTime(item.getCreateTime());
            borrowRecord.setBorrowShouldReturnTime(DateUtils.addDays(borrowRecord.getBorrowLendTime(),item.getBorrowDays()));
            borrowRecord.setBorrowStatus(BooksBorrowStatus.NORMAL.getCode());
            borrowRecord.setBorrowRecordType(BorrowRecordType.BORROWING.getCode());
            borrowRecord.setCreateId(item.getCreateId());
            borrowRecord.setCreateBy(item.getCreateBy());
            borrowRecord.setOperateTerrace(item.getOperateTerrace());
            borrowRecord.setOperateCard(item.getBorrowCard());

            borrowRecord.setBooksId(item.getBooksId());
            borrowRecord.setBooksName(item.getBooksName());
            borrowRecord.setBooksIsbn(item.getBooksIsbn());
            borrowRecord.setBooksCoverPhoto(item.getBooksCoverPhoto());

            borrowRecord.setBooksCopyId(item.getBooksCopyId());
            borrowRecord.setBooksCopyRfid(item.getBooksCopyRfid());
            borrowRecord.setBooksCopyLicense(item.getBooksCopyLicense());

            borrowRecord.setBookShelfId(item.getBookShelfId());
            borrowRecord.setBookShelfName(item.getBookShelfName());

            borrowRecord.setStudentName(item.getStudentName());
            borrowRecord.setStudentNumber(item.getStudentNumber());

            borrowRecord.setBookShelfId(item.getBookShelfId());
            borrowRecord.setBookShelfName(item.getBookShelfName());

            borrowRecordList.add(borrowRecord);
        });

        // 修改书籍副本状态
        if(booksCopyService.updateBatchById(booksCopyList)){
            // 批量添加借阅记录
            if(borrowRecordService.saveBatch(borrowRecordList)) {
                // 发送通知
                BookOnLend bookOnLend = new BookOnLend();
                bookOnLend.setList(booksBorrowList.stream().map(item -> {
                    BookOnLend.BookOnLendMessage bookOnLendMessage = new BookOnLend.BookOnLendMessage();
                    bookOnLendMessage.setBooksName(item.getBooksName());
                    bookOnLendMessage.setBooksCopyLicense(item.getBooksCopyLicense());
                    bookOnLendMessage.setOperateTerrace(item.getOperateTerrace());
                    return bookOnLendMessage;
                }).collect(Collectors.toList()));
                // 发送借阅书籍消息
                globalServerPoint.send(bookOnLend);
                return Boolean.TRUE;
            }
        }
        throw new RuntimeException("借阅失败");
    }

    /**
     * 根据卡号查询借阅记录列表
     *
     * @param rfid rfid集合
     * @return 借阅集合
     */
    @Override
    public List<BooksJoinBorrowRecord> selectBooksBorrowListByRfid(List<String> rfid) {
        return baseMapper.selectBooksBorrowListByRfid(rfid).stream().filter(f -> f.getBorrowId() != null).collect(Collectors.toList());
    }

    /**
     * 根据借阅id查询书籍等信息
     *  - 书籍信息（主要）
     *  - 规则信息
     *  - 书架信息
     *  - 产生的记录信息（主要）
     *  # 看记录信息而已，不用判断删除
     */
    @Override
    public BorrowJoinBooksMultiInfo selectBorrowJoinBooksMultiInfoByBorrowId(Long borrowId) {
        return baseMapper.selectBorrowJoinBooksMultiInfoByBorrowId(borrowId);
    }

    /**
     * 根据索书号查询借阅记录列表
     *
     * @param license 索书号
     * @return 借阅集合
     */
    @Override
    public BooksJoinBorrowRecord selectBooksBorrowListByLicense(String license) {
        return baseMapper.selectBooksBorrowListByLicense(license);
    }


    /**
     * 根据rfid查询可借阅书籍记录列表
     *
     * @param rfid rfid集合
     * @return 借阅集合
     */
    @Override
    public List<BooksJoinBorrowActive> selectBooksActiveBorrowListByRfid(List<String> rfid) {
        return baseMapper.selectBooksActiveBorrowListByRfid(rfid);
    }

    /**
     * 归还功能
     *
     * @param booksBorrowList 借阅集合
     * @return 借阅集合
     */
    @Override
    @Transactional(rollbackFor = Exception.class , isolation = Isolation.READ_COMMITTED)
    public boolean returnFunction(List<BooksJoinBorrowRecord> booksBorrowList) {

        // 当前借阅人
        List<Student> students = studentService.list(Wrappers.lambdaQuery(Student.class).in(Student::getStudentCardNumber, booksBorrowList.stream().map(BooksJoinBorrowRecord::getBorrowCard).distinct().collect(Collectors.toList())));
        if(students.isEmpty()) {
            throw new RuntimeException("借阅人信息有误");
        }

        List<BooksBorrow> updates = booksBorrowList.stream()
            .map(join -> {
                BooksBorrow booksBorrow = new BooksBorrow()
                    .setBorrowReturnTime(DateUtils.getNowDate())
                    .setBorrowStatus(BooksBorrowStatus.RETURN.getCode())
                    .setBorrowId(join.getBorrowId())
                    // 自助机的时候是没有用户存在的
                    .setCreateId(join.getCreateId())
                    .setCreateBy(join.getCreateBy())
                    .setUpdateId(join.getUpdateId())
                    .setUpdateBy(join.getUpdateBy());
                // 学生信息
                Student student = students.stream().filter(s -> s.getStudentCardNumber().equals(join.getBorrowCard())).findFirst().orElse(null);
                if(student == null) {
                    throw new RuntimeException("归还书籍《"+ join.getBooksName() +"》时，未找到["+ join.getBorrowCard() +"]学生信息");
                }
                // 学生最新卡号
                booksBorrow.setBorrowCard(student.getStudentCardNumber());
                return booksBorrow;
            }).collect(Collectors.toList());
        updateBatchById(updates);

        // 批量添加归还记录
        List<BorrowFineRecord> borrowFineRecordList = new ArrayList<>();
        List<BorrowRecord> borrowRecordList = new ArrayList<>();
        List<BooksCopy> booksCopyList = new ArrayList<>();
        // 发送归还信息
        List<BookOnReturn.BookOnReturnMessage> returnMegList = new ArrayList<>();
        // 收取了滞纳金的借阅id
        List<Long> amountBorrowIds = new ArrayList<>();
        booksBorrowList.forEach(item -> {

            // 学生信息
            Student student = students.stream().filter(s -> s.getStudentCardNumber().equals(item.getBorrowCard())).findFirst().orElse(null);
            if(student == null) {
                throw new RuntimeException("归还书籍《"+ item.getBooksName() +"》时，未找到["+ item.getBorrowCard() +"]学生信息");
            }

            BooksCopy booksCopy = new BooksCopy();
            booksCopy.setBooksCopyId(item.getBooksCopyId());
            booksCopy.setBooksCopyStatus(BooksCopyStatus.NORMAL.getCode());
            // 自助机的时候是没有用户存在的
            booksCopy.setCreateId(item.getCreateId());
            booksCopy.setCreateBy(item.getCreateBy());
            booksCopy.setUpdateId(item.getUpdateId());
            booksCopy.setUpdateBy(item.getUpdateBy());
            booksCopyList.add(booksCopy);

            BorrowRecord borrowRecord = new BorrowRecord();
            borrowRecord.setBorrowId(item.getBorrowId());
            borrowRecord.setBorrowCard(item.getBorrowCard());
            borrowRecord.setBorrowStatus(BooksBorrowStatus.RETURN.getCode());
            borrowRecord.setBorrowRecordType(BorrowRecordType.RETURN.getCode());
            borrowRecord.setBorrowReturnTime(DateUtils.getNowDate());
            borrowRecord.setCreateBy(item.getCreateBy());
            borrowRecord.setCreateId(item.getCreateId());
            borrowRecord.setOperateCard(item.getOperateCard());
            borrowRecord.setOperateTerrace(item.getOperateTerrace());
            // 归还意味着一个借阅的结束（视图添加最后一次续借相关数据）
            borrowRecord.setBorrowRenewTime(item.getBorrowRenewTime());
            borrowRecord.setBorrowRenewDays(item.getBorrowRenewDays());
            borrowRecord.setBorrowLendTime(item.getCreateTime());
            borrowRecord.setBorrowLendDays(item.getBorrowDays());
            borrowRecord.setBorrowShouldReturnTime(item.getBorrowShouldReturnTime());

            borrowRecord.setBooksId(item.getBooksId());
            borrowRecord.setBooksName(item.getBooksName());
            borrowRecord.setBooksIsbn(item.getBooksIsbn());
            borrowRecord.setBooksCoverPhoto(item.getBooksCoverPhoto());

            borrowRecord.setBookShelfId(item.getBookShelfId());
            borrowRecord.setBookShelfName(item.getBookShelfName());

            borrowRecord.setBooksCopyId(item.getBooksCopyId());
            borrowRecord.setBooksCopyLicense(item.getBooksCopyLicense());
            borrowRecord.setBooksCopyRfid(item.getBooksCopyRfid());

            borrowRecord.setStudentName(student.getStudentName());
            borrowRecord.setStudentNumber(student.getStudentNumber());
            borrowRecordList.add(borrowRecord);

            BookOnReturn.BookOnReturnMessage bookOnReturnMessage = new BookOnReturn.BookOnReturnMessage();
            bookOnReturnMessage.setBooksName(item.getBooksName());
            bookOnReturnMessage.setBooksCopyLicense(item.getBooksCopyLicense());
            bookOnReturnMessage.setOperateTerrace(item.getOperateTerrace());

            // 滞纳金
            if(item.getBorrowTakeTarryFine() != null && BigDecimal.ZERO.compareTo(item.getBorrowTakeTarryFine()) < 0) {
                // 添加滞留金记录
                BorrowFineRecord borrowFineRecord = new BorrowFineRecord();
                borrowFineRecord.setBorrowId(item.getBorrowId());
                borrowFineRecord.setBorrowCard(item.getBorrowCard());
                borrowFineRecord.setBorrowStatus(BooksBorrowStatus.OVERDUE.getCode());
                borrowFineRecord.setBorrowRecordType(BorrowRecordType.RETURN.getCode());

                borrowFineRecord.setBooksIsbn(item.getBooksIsbn());
                borrowFineRecord.setBooksName(item.getBooksName());
                borrowFineRecord.setBooksCoverPhoto(item.getBooksCoverPhoto());

                borrowFineRecord.setBooksCopyId(item.getBooksCopyId());
                borrowFineRecord.setBooksCopyLicense(item.getBooksCopyLicense());

                borrowFineRecord.setBookShelfId(item.getBookShelfId());
                borrowFineRecord.setBookShelfName(item.getBookShelfName());

                borrowFineRecord.setStudentName(student.getStudentName());
                borrowFineRecord.setStudentNumber(student.getStudentNumber());

                borrowFineRecord.setBorrowFineRenewTime(item.getBorrowRenewTime());
                borrowFineRecord.setBorrowFineRenewDays(item.getBorrowRenewDays());
                borrowFineRecord.setBorrowFineLendTime(item.getCreateTime());
                borrowFineRecord.setBorrowFineLendDays(item.getBorrowDays());
                borrowFineRecord.setBorrowFineShouldReturnTime(item.getBorrowShouldReturnTime());
                borrowFineRecord.setBorrowFineOverdueDays(item.getBorrowOverdueDays());
                borrowFineRecord.setBorrowFineAmount(item.getBorrowTakeTarryFine());
                borrowFineRecord.setCreateBy(item.getCreateBy());
                borrowFineRecord.setCreateId(item.getCreateId());

                bookOnReturnMessage.setBorrowTakeTarryFine(item.getBorrowTakeTarryFine());
                borrowFineRecordList.add(borrowFineRecord);
                amountBorrowIds.add(item.getBorrowId());
            }
            returnMegList.add(bookOnReturnMessage);

        });
        // 修改书籍副本状态
        booksCopyService.updateBatchById(booksCopyList);
        // 借阅操作记录
        borrowRecordService.saveBatch(borrowRecordList);

        // 给滞纳金记录赋值 借阅记录id
        if(borrowRecordList.size() > 0) {
            borrowRecordList.stream()
                .filter(borrowRecord -> borrowRecord.getBorrowRecordId() != null && amountBorrowIds.stream().anyMatch(take -> take.equals(borrowRecord.getBorrowId())))
                .forEach(br -> {
                    borrowFineRecordList.stream()
                        .filter(bf -> bf.getBorrowId().equals(br.getBorrowId()))
                        .findFirst()
                        .ifPresent(bf -> bf.setBorrowRecordId(br.getBorrowRecordId()));
                });
            borrowFineRecordService.saveBatch(borrowFineRecordList);

            // 发送归还消息
            BookOnReturn bookOnReturn = new BookOnReturn();
            bookOnReturn.setList(returnMegList);
            globalServerPoint.send(bookOnReturn);
        }
        return Boolean.TRUE;
    }

    /**
     * 续借功能
     *
     * @param booksBorrow 借阅集合
     * @return 借阅集合
     */
    @Override
    @Transactional(rollbackFor = Exception.class , isolation = Isolation.READ_COMMITTED)
    public boolean renewalFunction(BooksJoinBorrowRecord booksBorrow) {
        this.renewalMultiFunction(Arrays.asList(booksBorrow));
        return Boolean.TRUE;
    }

    /**
     * 批量续借功能
     *
     * @param booksBorrows 借阅集合
     * @return 借阅集合
     */
    @Override
    @Transactional(rollbackFor = Exception.class , isolation = Isolation.READ_COMMITTED)
    public boolean renewalMultiFunction(List<BooksJoinBorrowRecord> booksBorrows) {
        // 当前借阅人
        List<Student> students = studentService.list(Wrappers.lambdaQuery(Student.class).in(Student::getStudentCardNumber, booksBorrows.stream().map(BooksJoinBorrowRecord::getBorrowCard).distinct().collect(Collectors.toList())));
        if(students.size() == 0) {
            throw new RuntimeException("学生信息有误");
        }

        // 更新列表
        List<BooksBorrow> updateList = new ArrayList<>();
        // 新增滞纳金记录
        List<BorrowFineRecord> borrowFineRecordList = new ArrayList<>();
        // 更新副本列表
        List<BooksCopy> booksCopyUpdateList = new ArrayList<>();
        // 新增(续)借阅记录
        List<BorrowRecord> borrowRecordList = new ArrayList<>();
        for (BooksJoinBorrowRecord booksBorrow : booksBorrows) {
            // 获取书本续借规则
            BooksRule booksRule = borrowRunService.selectBooksRuleInfoByBooksCopyId(booksBorrow.getBooksCopyId());
            if(booksRule == null) {
                throw new RuntimeException("未查询到借阅信息");
            }
            // 判断书籍是否可以续借
            if (booksRule.getBooksRuleRenew().equals(BooksRuleRenew.NORMAL.getCode())) {
                // 根据借阅id和续借类型查询续借次数
                QueryWrapper<BorrowRecord> borrowRecordQueryWrapper = new QueryWrapper<>();
                borrowRecordQueryWrapper
                    .eq("borrow_id", booksBorrow.getBorrowId())
                    .eq("borrow_record_type", BorrowRecordType.RENEW.getCode());
                long count = borrowRecordService.list(borrowRecordQueryWrapper).size();
                if (booksRule.getBooksRuleRenewNum() <= count) {
                    throw new RuntimeException("索书号[" + booksBorrow.getBooksCopyLicense() + "]续借次数已超过");
                }
            }else {
                throw new RuntimeException("《" + booksBorrow.getBooksName() + "》书籍不允许续借");
            }

            // 查询学生信息
            Student student = students.stream().filter(s -> s.getStudentCardNumber().equals(booksBorrow.getBorrowCard())).findFirst().orElse(null);
            if(student == null) {
                throw new RuntimeException("续借书籍《"+ booksBorrow.getBooksName() +"》时，未找到["+ booksBorrow.getBorrowCard() +"]学生信息");
            }
            booksBorrow.setStudentName(student.getStudentName());
            booksBorrow.setStudentNumber(student.getStudentNumber());

            // 续借应还日期
            Date shouldReturnTime;
            Calendar nowDateCalendar = Calendar.getInstance();
            nowDateCalendar.setTime(DateUtils.getNowDate());
            Calendar shouldReturnDateCalendar = Calendar.getInstance();
            shouldReturnDateCalendar.setTime(booksBorrow.getBorrowShouldReturnTime());
            // 逾期
            if(LocalDate.of(nowDateCalendar.get(Calendar.YEAR),nowDateCalendar.get(Calendar.MONTH) + 1,nowDateCalendar.get(Calendar.DAY_OF_MONTH))
                    .compareTo(LocalDate.of(shouldReturnDateCalendar.get(Calendar.YEAR),shouldReturnDateCalendar.get(Calendar.MONTH) + 1,shouldReturnDateCalendar.get(Calendar.DAY_OF_MONTH))) > 0) {
                shouldReturnTime = DateUtils.addDays(nowDateCalendar.getTime(), booksBorrow.getBorrowRenewDays());
            }
            // 未逾期
            else {
                shouldReturnTime = DateUtils.addDays(shouldReturnDateCalendar.getTime(), booksBorrow.getBorrowRenewDays());
            }

            // 能续借证明是正常的
            BooksBorrow booksBorrow1 = new BooksBorrow();
            booksBorrow1.setBorrowId(booksBorrow.getBorrowId());
            booksBorrow1.setBorrowStatus(BooksBorrowStatus.NORMAL.getCode());
            booksBorrow1.setBorrowRenewDays(booksBorrow.getBorrowRenewDays());
            booksBorrow1.setBorrowRenewTime(DateUtils.getNowDate());
            booksBorrow1.setBorrowShouldReturnTime(shouldReturnTime);
            booksBorrow1.setCreateBy(booksBorrow.getCreateBy());
            booksBorrow1.setCreateId(booksBorrow.getCreateId());
            booksBorrow1.setUpdateBy(booksBorrow.getUpdateBy());
            booksBorrow1.setUpdateId(booksBorrow.getUpdateId());
            updateList.add(booksBorrow1);

            BooksCopy booksCopy = new BooksCopy();
            booksCopy.setBooksCopyId(booksBorrow.getBooksCopyId());
            booksCopy.setBooksCopyStatus(BooksCopyStatus.LEND.getCode());
            booksCopy.setCreateBy(booksBorrow.getCreateBy());
            booksCopy.setCreateId(booksBorrow.getCreateId());
            booksCopy.setUpdateBy(booksBorrow.getUpdateBy());
            booksCopy.setUpdateId(booksBorrow.getUpdateId());
            // 修改书籍副本状态
            booksCopyUpdateList.add(booksCopy);

            // 添加续借记录
            BorrowRecord borrowRecord = new BorrowRecord();
            borrowRecord.setBorrowId(booksBorrow.getBorrowId());
            borrowRecord.setBorrowCard(booksBorrow.getBorrowCard());
            borrowRecord.setBorrowStatus(BooksBorrowStatus.NORMAL.getCode());
            borrowRecord.setBorrowRecordType(BorrowRecordType.RENEW.getCode());
            borrowRecord.setBorrowRenewTime(booksBorrow.getBorrowRenewTime());
            borrowRecord.setBorrowRenewDays(booksBorrow.getBorrowRenewDays());
            borrowRecord.setBorrowShouldReturnTime(shouldReturnTime);
            borrowRecord.setCreateBy(booksBorrow.getCreateBy());
            borrowRecord.setCreateId(booksBorrow.getCreateId());
            borrowRecord.setOperateCard(booksBorrow.getOperateCard());
            borrowRecord.setOperateTerrace(booksBorrow.getOperateTerrace());

            borrowRecord.setBooksId(booksBorrow.getBooksId());
            borrowRecord.setBooksName(booksBorrow.getBooksName());
            borrowRecord.setBooksIsbn(booksBorrow.getBooksIsbn());
            borrowRecord.setBooksCoverPhoto(booksBorrow.getBooksCoverPhoto());

            borrowRecord.setBookShelfId(booksBorrow.getBookShelfId());
            borrowRecord.setBookShelfName(booksBorrow.getBookShelfName());

            borrowRecord.setBooksCopyId(booksBorrow.getBooksCopyId());
            borrowRecord.setBooksCopyLicense(booksBorrow.getBooksCopyLicense());
            borrowRecord.setBooksCopyRfid(booksBorrow.getBooksCopyRfid());

            borrowRecord.setStudentName(booksBorrow.getStudentName());
            borrowRecord.setStudentNumber(booksBorrow.getStudentNumber());
            borrowRecordList.add(borrowRecord);

            // 只有逾期的时候才会 = 1（结果由查询得出，实际并不在数据库。现在更新后才存在）
            if(booksBorrow.getBorrowTakeTarryFine() != null && BigDecimal.ZERO.compareTo(booksBorrow.getBorrowTakeTarryFine()) < 0) {
                // 添加滞留金记录
                BorrowFineRecord borrowFineRecord = new BorrowFineRecord()
                    .setBorrowId(booksBorrow.getBorrowId())
                    .setBorrowCard(booksBorrow.getBorrowCard())
                    .setBorrowStatus(BooksBorrowStatus.OVERDUE.getCode())
                    .setBorrowRecordType(BorrowRecordType.RENEW.getCode())

                    .setBooksCoverPhoto(booksBorrow.getBooksCoverPhoto())
                    .setBooksIsbn(booksBorrow.getBooksIsbn())
                    .setBooksName(booksBorrow.getBooksName())

                    .setBooksCopyId(booksBorrow.getBooksCopyId())
                    .setBooksCopyLicense(booksBorrow.getBooksCopyLicense())

                    .setBookShelfId(booksBorrow.getBookShelfId())
                    .setBookShelfName(booksBorrow.getBookShelfName())

                    .setStudentName(booksBorrow.getStudentName())
                    .setStudentNumber(booksBorrow.getStudentNumber())

                    .setBorrowFineRenewTime(booksBorrow.getBorrowRenewTime())
                    .setBorrowFineRenewDays(booksBorrow.getBorrowRenewTime() == null ?null :booksBorrow.getBorrowRenewDays())
                    .setBorrowFineLendTime(booksBorrow.getCreateTime())
                    .setBorrowFineLendDays(booksBorrow.getBorrowDays())
                    .setBorrowFineShouldReturnTime(booksBorrow.getBorrowShouldReturnTime())
                    .setBorrowFineOverdueDays(booksBorrow.getBorrowOverdueDays())
                    .setBorrowFineAmount(booksBorrow.getBorrowTakeTarryFine())

                    .setCreateBy(booksBorrow.getCreateBy())
                    .setCreateId(booksBorrow.getCreateId())

                    .setOperateCard(booksBorrow.getOperateCard())
                    .setOperateTerrace(booksBorrow.getOperateTerrace());
                // 滞纳金记录
                borrowFineRecordList.add(borrowFineRecord);
            }
        }

        if(updateList.size() > 0 && updateBatchById(updateList)) {
            booksCopyService.updateBatchById(booksCopyUpdateList);
            borrowRecordService.saveBatch(borrowRecordList);

            /// 发送通知
            BookOnRenew bookOnRenew = new BookOnRenew();
            bookOnRenew.setList(borrowRecordList.stream().map(item -> {
                BookOnRenew.BookOnRenewMessage bookOnRenewMessage = new BookOnRenew.BookOnRenewMessage();
                bookOnRenewMessage.setBooksName(item.getBooksName());
                bookOnRenewMessage.setBooksCopyLicense(item.getBooksCopyLicense());
                bookOnRenewMessage.setBorrowRenewTime(item.getBorrowRenewTime());
                bookOnRenewMessage.setBorrowRenewDays(item.getBorrowRenewDays());
                bookOnRenewMessage.setBorrowRenewDays(item.getBorrowRenewDays());
                bookOnRenewMessage.setOperateTerrace(item.getOperateTerrace());
                return bookOnRenewMessage;
            }).collect(Collectors.toList()));
            // 发送续借书籍消息
            globalServerPoint.send(bookOnRenew);

            if(borrowFineRecordList.size() > 0) {
                // 填充滞纳金是那个操作记录存
                borrowFineRecordList.forEach(bf ->
                    borrowRecordList.stream()
                        .filter(br -> br.getBorrowId().equals(bf.getBorrowId()))
                        .findFirst()
                        .ifPresent(br -> bf.setBorrowRecordId(br.getBorrowRecordId()))
                );
                borrowFineRecordService.saveBatch(borrowFineRecordList);
            }
        }
        return true;
    }


    /**
     * 查询书籍借出待归还列表
     *
     * @return 借阅集合
     */
    @Override
    public List<BooksJoinBorrowRecord> selectBooksBorrowLendList(BooksJoinBorrowRecord booksJoinBorrowRecord) {
        return getBaseMapper().selectBooksBorrowLendList(booksJoinBorrowRecord);
    }

    /**
     * 查询逾期记录列表
     *
     * @return 逾期集合
     */
    @Override
    public List<BooksJoinBorrowRecord> selectBooksBorrowBeOverdueList(BooksJoinBorrowRecord booksJoinBorrowRecord) {
        return baseMapper.selectBooksBorrowBeOverdueList(booksJoinBorrowRecord).stream().filter(f -> f.getBorrowId() != null).collect(Collectors.toList());
    }

    /**
     * 查询逾期记录数量
     *  - 将分组去掉了，直接查逾期总数
     * @return 逾期数量
     */
    @Override
    public Long selectBooksBorrowBeOverdueCount(BooksJoinBorrowRecord booksJoinBorrowRecord) {
        return baseMapper.selectBooksBorrowBeOverdueCount(booksJoinBorrowRecord);
    }

    @Override
    public Long selectBooksBorrowBeLendCount(BooksJoinBorrowRecord booksJoinBorrowRecord) {
        return baseMapper.selectBooksBorrowBeLendCount(booksJoinBorrowRecord);
    }

    /**
     * 检查是否能够正常借出
     *  - 网络延迟实际上已经借出
     *  - 数据库已经软删除的数据
     * @param booksBorrowList 检查集合
     */
    @Override
    @Transactional(readOnly = true,isolation = Isolation.READ_COMMITTED)
    public void checkLend(List<BooksJoinBorrowRecord> booksBorrowList) {
        BooksJoinBooksCopy booksJoinBooksCopy = new BooksJoinBooksCopy();
        booksJoinBooksCopy.setQueryRfids(booksBorrowList.stream().map(BooksJoinBorrowRecord::getBooksCopyRfid).collect(Collectors.toList()));
        List<BooksJoinBooksCopy> booksJoinBooksCopies = booksCopyService.selectBooksCopyJoinBooksList(booksJoinBooksCopy);
        if(booksJoinBooksCopies.isEmpty()) {
            log.error("借阅的RFID查询结果为空，原因是都已经软删除");
            throw new RuntimeException("未查询到可归还书籍");
        }else {
            // 是否有借出的副本
            String hint = booksJoinBooksCopies.stream()
                .filter(c ->  ! BooksCopyStatus.NORMAL.equals(c.getBooksCopyStatus()))
                .map(BooksJoinBooksCopy::getBooksCopyLicense)
                .collect(Collectors.joining(","));
            if(! hint.isEmpty()) {
                throw new RuntimeException("索书号["+hint+"]已借出，请移除");
            }

            // 学生借阅情况
            Map<String, List<BooksJoinBorrowRecord>> studentBorrow = booksBorrowList.stream()
                .collect(Collectors.groupingBy(BooksJoinBorrowRecord::getBorrowCard));
            // 是否已经超出借阅上限（每个人多少本，默认五本）
            long maxLendConfig = Long.parseLong(
                StringUtils.nvl(SpringUtils.getBean(ISysConfigService.class).selectConfigByKey(SysConfigConstants.MAX_LEND_CONFIG_KEY),"5")
            );
            BooksJoinBorrowRecord find = new BooksJoinBorrowRecord();
            String limit =studentBorrow.keySet().stream()
                .filter(borrowCard -> {
                    find.setBorrowCard(borrowCard);
                    return baseMapper.selectBooksBorrowBeLendCount(find) + studentBorrow.get(borrowCard).size() > maxLendConfig;
                }).collect(Collectors.joining(","));
            if(! limit.isEmpty()) {
                throw new RuntimeException("学生["+limit+"]已超出借阅上限，请移除");
            }
        }
    }

    /**
     * 检查是否能够正常归还
     *  - 网络延迟实际上已经归还
     *  - 数据库已经软删除的数据
     * @param booksBorrowList 检查集合
     */
    @Override
    @Transactional(readOnly = true,isolation = Isolation.READ_COMMITTED)
    public void checkReturn(List<BooksJoinBorrowRecord> booksBorrowList) {
        BooksJoinBooksCopy booksJoinBooksCopy = new BooksJoinBooksCopy();
        booksJoinBooksCopy.setQueryRfids(booksBorrowList.stream().map(BooksJoinBorrowRecord::getBooksCopyRfid).collect(Collectors.toList()));
        List<BooksJoinBooksCopy> booksJoinBooksCopies = booksCopyService.selectBooksCopyJoinBooksList(booksJoinBooksCopy);
        if(booksJoinBooksCopies.isEmpty()) {
            log.error("归还的RFID查询结果为空，原因是都已经软删除");
            throw new RuntimeException("未查询到可归还书籍");
        }else {
            String hint = booksJoinBooksCopies.stream()
                    .filter(c -> !BooksCopyStatus.LEND.equals(c.getBooksCopyStatus()))
                    .map(BooksJoinBooksCopy::getBooksCopyLicense)
                    .collect(Collectors.joining(","));
            if(! hint.isEmpty()) {
                throw new RuntimeException("索书号["+hint+"]未借出，请移除");
            }
        }
    }

}
